/*

* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Smart-Shop开源商城系统/ Java商城-首选电商平台系统 请务必保留此注释头信息
* |     开源地址: https://gitee.com/ningbo-qishan/gruul-mall
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     可正常分享和学习源码,未经授权 不可商用！
* |     商业版中台购买/开源版商业授权 联系技术客服
* |     官网:  https://www.73app.cn/
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Copyright (c) 2016-2999 宁波启山智软科技有限公司
* |     版权所有 ,侵权必究！
* ------------------------------------------------------------------------

*/
package com.medusa.gruul.multi.client.account.service.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.medusa.gruul.common.core.auth.client.context.PlatformContextHolder;
import com.medusa.gruul.common.core.auth.client.helper.ISecurity;
import com.medusa.gruul.common.core.auth.model.enums.Gender;
import com.medusa.gruul.common.core.auth.model.enums.OauthTypeEnum;
import com.medusa.gruul.common.core.auth.model.enums.UserStatus;
import com.medusa.gruul.common.core.auth.model.enums.WechatAuthType;
import com.medusa.gruul.common.core.exception.ServiceException;
import com.medusa.gruul.common.core.util.SystemCode;
import com.medusa.gruul.multi.client.account.api.entity.*;
import com.medusa.gruul.multi.client.account.api.model.dto.WechatOpenUserDTO;
import com.medusa.gruul.multi.client.account.service.helper.UserHelper;
import com.medusa.gruul.multi.client.account.service.mp.service.*;
import com.medusa.gruul.multi.client.account.service.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * @author 张治保
 * date 2021/12/4
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final Snowflake shopUserIdSnowflake;
    private final IMiniAccountExtendsService miniAccountExtendsService;
    private final IMultiClientAccountService multiClientAccountService;
    private final IMultiClientAccountAuthService multiClientAccountAuthService;
    private final IMultiClientAccountDataService multiClientAccountDataService;
    private final IMultiClientAccountWechatService multiClientAccountWechatService;
    private final IMiniAccountService miniAccountService;
    private final IMiniAccountOauthsService miniAccountOauthsService;
    private final IMultiClientAccountShopService multiClientAccountShopService;

    /**
     * 获取商铺用户id
     */
    @Override
    public String getShopUserId(String userId) {
        /*
         * 查询用户与店铺关系表
         */
        miniAccountExtendsService.lambdaUpdate().set(MiniAccountExtends::getCurrentStatus, Boolean.FALSE).eq(MiniAccountExtends::getUserId, userId);
        MiniAccountExtends accountExtends = miniAccountExtendsService.lambdaQuery().eq(MiniAccountExtends::getUserId, userId).one();
        if (accountExtends == null) {
            //新增用户商铺关系
            accountExtends = new MiniAccountExtends()
                .setUserId(userId)
                .setIsBlacklist(Boolean.FALSE)
                .setConsumeNum(0)
                .setCurrentStatus(Boolean.TRUE)
                .setConsumeTotleMoney(BigDecimal.ZERO)
                .setShopUserId(shopUserIdSnowflake.nextIdStr())
                .setShopId(ISecurity.shopId().must())
                .setLastLoginTime(LocalDateTime.now());
            accountExtends.setTenantId(ISecurity.tenantId().must());
            miniAccountExtendsService.save(accountExtends);
        } else {
            accountExtends.setCurrentStatus(Boolean.TRUE)
                .setShopId(ISecurity.shopId().must());
            miniAccountExtendsService.updateById(accountExtends);

        }
        return accountExtends.getShopUserId();
    }

    @Override
    public MultiClientAccount newAccount() {
        return this.newAccount(null);
    }

    @Override
    public MultiClientAccount newAccount(String mobile) {
        String salt = RandomUtil.randomString(11);
        String password = RandomUtil.randomString(15);
        MultiClientAccount account = new MultiClientAccount()
            .setUsername(RandomUtil.randomString(20))
            .setSalt(salt)
            .setPassword(UserHelper.passwordEncrypt(password, salt))
            .setEmail(null)
            .setMobile(mobile)
            .setStatus(UserStatus.OK);
        boolean success = multiClientAccountService.save(account);
        if (!success) {
            throw new ServiceException(SystemCode.DATA_ADD_FAILED);
        }
        return account;
    }

    @Override
    public MultiClientAccountAuth newAuth(Long accountId, String userId) {

        MultiClientAccountAuth auth = new MultiClientAccountAuth();
        auth.setAccountId(accountId)
            .setAuthPlatform(ISecurity.authPlatform().must())
            .setPlatform(ISecurity.platform().must());
        boolean success = multiClientAccountAuthService.save(auth);
        if (!success) {
            throw new ServiceException(SystemCode.DATA_ADD_FAILED);
        }
        return auth;
    }

    @Override
    public MultiClientAccountData newData(Long accountId, String userId) {
        MultiClientAccountData data = new MultiClientAccountData()
            .setFirstLoginTime(LocalDateTime.now())
            .setGender(Gender.UNKNOWN)
            .setAccountId(accountId);

        MiniAccount miniAccount = miniAccountService.lambdaQuery().eq(MiniAccount::getUserId, userId).one();
        if (miniAccount != null) {
            data.setNickname(miniAccount.getNikeName())
                .setAvatar(miniAccount.getAvatarUrl())
                .setGender(miniAccount.getGender() == null ? Gender.UNKNOWN : miniAccount.getGender())
                .setLanguage(miniAccount.getLanguage());
        } else {
            data.setNickname(RandomUtil.randomString(5))
                .setAvatar("https://pic1.zhimg.com/50/v2-6afa72220d29f045c15217aa6b275808_hd.jpg");
        }

        boolean success = multiClientAccountDataService.save(data);
        if (!success) {
            throw new ServiceException(SystemCode.DATA_ADD_FAILED);
        }
        return data;
    }

    @Override
    public MultiClientAccountShop newAccountShop(Long accountId, String userId) {
        MultiClientAccountShop accountShop = new MultiClientAccountShop()
            .setAccountId(accountId)
            .setUserId(userId)
            .setShopId(ISecurity.shopId().must())
            .setShopUserId(
                this.getShopUserId(userId)
            );
        boolean success = multiClientAccountShopService.save(accountShop);
        if (!success) {
            throw new ServiceException(SystemCode.DATA_ADD_FAILED);
        }
        return accountShop;
    }

    @Override
    public MultiClientAccountData newData(Long accountId, String userId, WechatOpenUserDTO user) {
        MultiClientAccountData data = new MultiClientAccountData();
        data.setAccountId(accountId)
            .setLanguage(user.getLanguage())
            .setNickname(user.getNickname())
            .setGender(Gender.UNKNOWN)
            .setAvatar(user.getHeadImgUrl())
            .setFirstLoginTime(LocalDateTime.now());
        MiniAccount miniAccount = miniAccountService.lambdaQuery().eq(MiniAccount::getUserId, userId).one();
        if (miniAccount != null) {
            data.setGender(miniAccount.getGender() == null ? Gender.UNKNOWN : miniAccount.getGender());
        }
        boolean success = multiClientAccountDataService.save(data);
        if (!success) {
            throw new ServiceException(SystemCode.DATA_ADD_FAILED);
        }
        return data;
    }

    @Override
    public MultiClientAccountWechat newWechat(Long accountId, String openId, String unionId, WechatAuthType type) {
        MultiClientAccountWechat wechat = multiClientAccountWechatService.lambdaQuery()
            .eq(MultiClientAccountWechat::getAccountId, accountId)
            .eq(MultiClientAccountWechat::getAuthType, type)
            .one();

        if (wechat != null) {
            if (!StrUtil.equals(openId, wechat.getOpenId()) || !StrUtil.equals(unionId, wechat.getUnionId())) {
                wechat.setOpenId(openId)
                    .setUnionId(unionId);
                multiClientAccountWechatService.updateById(wechat);
            }
            return wechat;
        }
        wechat = new MultiClientAccountWechat();
        wechat.setAccountId(accountId)
            .setOpenId(openId)
            .setUnionId(unionId)
            .setAuthType(type);
        boolean success = multiClientAccountWechatService.save(wechat);
        if (!success) {
            throw new ServiceException(SystemCode.DATA_ADD_FAILED);
        }
        return wechat;
    }

    @Override
    public MultiClientAccountWechat newWechat(Long accountId, String userId) {
        /*
         * 查询小程序认证是否存在
         */
        MiniAccountOauths oauths = miniAccountOauthsService.lambdaQuery().eq(MiniAccountOauths::getUserId, userId).one();
        return oauths == null ? null : newWechat(accountId, oauths.getOpenId(), oauths.getUnionId(), oauths.getOauthType() == OauthTypeEnum.WX_MINI ? WechatAuthType.WECHAT_MINI_APP : WechatAuthType.WECHAT_MP);
    }
}
